package com.panfeng.xcloud.boss.provider.assets.config;

import com.panfeng.xcloud.boss.provider.assets.security.AssetsAccessDeniedHandler;
import com.panfeng.xcloud.boss.provider.assets.security.AssetsAuthExceptionEntryPoint;
import com.panfeng.xcloud.common.security.properties.SecurityProperties;
import com.panfeng.xcloud.common.security.utils.IgnoreUrlMatcher;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

import java.util.List;

/**
 * 资源服务器配置类
 *
 * @author xiaobo
 * @date 2018-03-15
 */
@Configuration
@EnableResourceServer
@Slf4j
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

	@Autowired
	private AssetsAccessDeniedHandler assetsAccessDeniedHandler;

	@Autowired
	private AssetsAuthExceptionEntryPoint assetsAuthExceptionEntryPoint;

	@Autowired
	private SecurityProperties securityProperties;

	@Override
	public void configure(ResourceServerSecurityConfigurer resources){
		resources.tokenServices(tokenServices());
		resources.tokenStore(jwtTokenStore());
	}

	@Bean
	@Primary
	public DefaultTokenServices tokenServices() {
		DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
		defaultTokenServices.setTokenStore(jwtTokenStore());
		return defaultTokenServices;
	}

	@Bean
	public JwtTokenStore jwtTokenStore() {
		return new JwtTokenStore(accessTokenConverter());
	}

	@Bean
	public JwtAccessTokenConverter accessTokenConverter() {
		JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
		String jwtSigningKey = securityProperties.getOauth2().getJwtSigningKey();
		converter.setSigningKey(jwtSigningKey);
		return converter;
	}

	@Bean
	public TokenEnhancer jwtTokenEnhancer() {
		return new AssetsTokenJwtEnhancer();
	}

	@Override
	public void configure(HttpSecurity http) throws Exception {
		ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http
				.headers().frameOptions().disable()
				.and()
				.csrf().disable()
				.exceptionHandling()
				.accessDeniedHandler(assetsAccessDeniedHandler)
				.authenticationEntryPoint(assetsAuthExceptionEntryPoint)
				.and()
				.authorizeRequests();

		List<String> ignoreUrls = IgnoreUrlMatcher.getIgnoreUrls();

		ignoreUrls.add("/druid/**");
		ignoreUrls.add("/actuator/**");
		ignoreUrls.add("/actuator");
		ignoreUrls.add("/swagger-ui.html");
		ignoreUrls.add("/swagger-resources/**");
		ignoreUrls.add("/v2/api-docs");
		ignoreUrls.add("/api/applications");

		int ignoreUrlSize = ignoreUrls.size();
		log.info(">>> 被排除的鉴权资源大小:{},资源详情:{}",ignoreUrlSize,ignoreUrls);
		ignoreUrls.forEach(url -> registry.antMatchers(url).permitAll());

		//除了异常被排除的链接之外，其他资源都需要认证
		registry
				.anyRequest()
				.authenticated();
	}
}
